package cn.xm.action;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.BeanUtils;

import cn.xm.service.UserService;
import cn.xm.utils.BaseServlet;
import cn.xm.utils.MD5;
import cn.xm.vo.User;

/**
 * Servlet implementation class UserServlet
 */
public class UserServlet extends BaseServlet {
	
	//调用Service层处理数据 创建一个UserService对象
	private UserService us = new UserService();
	/**
	 * 验证码校验
	 */
	public void checkMyReload(HttpServletRequest req,HttpServletResponse resp) throws IOException{
		String checkcode=req.getParameter("checkCode");  
        if(checkcode.equals("")||checkcode==null){  
        	resp.getWriter().println("3");
        }else{  
            HttpSession session = req.getSession(true);
			if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){  
            	resp.getWriter().println("1");
            }else{  
            	resp.getWriter().println("0");  
            }  
        }  
	}
	/**
	 * 验证码
	 */
	 private static final long serialVersionUID = 1L;  
	  
	    
	    /*该方法主要作用是获得随机生成的颜色*/   
	    public Color getRandColor(int s,int e){  
	        Random random=new Random ();  
	        if(s>255) s=255;  
	        if(e>255) e=255;  
	        int r,g,b;  
	        r=s+random.nextInt(e-s);    //随机生成RGB颜色中的r值  
	        g=s+random.nextInt(e-s);    //随机生成RGB颜色中的g值  
	        b=s+random.nextInt(e-s);    //随机生成RGB颜色中的b值  
	        return new Color(r,g,b);  
	    }  
	  
	    public void PictureCheckCode (HttpServletRequest request, HttpServletResponse response)  
	            throws IOException {
	    	System.out.println("-----------------> PictureCheckCode");
	        //设置不缓存图片  
	        response.setHeader("Pragma", "No-cache");  
	        response.setHeader("Cache-Control", "No-cache");  
	        response.setDateHeader("Expires", 0);  
	        //指定生成的响应图片,一定不能缺少这句话,否则错误.  
	        response.setContentType("image/jpeg");  
	        int width=86,height=22;     //指定生成验证码的宽度和高度  
	        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //创建BufferedImage对象,其作用相当于一图片  
	        Graphics g=image.getGraphics();     //创建Graphics对象,其作用相当于画笔  
	        Graphics2D g2d=(Graphics2D)g;       //创建Grapchics2D对象  
	        Random random=new Random();  
	        Font mfont=new Font("楷体",Font.BOLD,16); //定义字体样式  
	        g.setColor(getRandColor(200,250));  
	        g.fillRect(0, 0, width, height);    //绘制背景  
	        g.setFont(mfont);                   //设置字体  
	        g.setColor(getRandColor(180,200));  
	          
	        //绘制100条颜色和位置全部为随机产生的线条,该线条为2f  
	        for(int i=0;i<100;i++){  
	            int x=random.nextInt(width-1);  
	            int y=random.nextInt(height-1);  
	            int x1=random.nextInt(6)+1;  
	            int y1=random.nextInt(12)+1;  
	            BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL); //定制线条样式  
	            Line2D line=new Line2D.Double(x,y,x+x1,y+y1);  
	            g2d.setStroke(bs);  
	            g2d.draw(line);     //绘制直线  
	        }  
	        //输出由英文，数字，和中文随机组成的验证文字，具体的组合方式根据生成随机数确定。  
	        String sRand="";  
	        String ctmp="";  
	        int itmp=0;  
	        //制定输出的验证码为四位  
	        for(int i=0;i<4;i++){  
	            switch(random.nextInt(2)){  
	                case 1:     //生成A-Z的字母  
	                     itmp=random.nextInt(26)+65;  
	                     ctmp=String.valueOf((char)itmp);
	                     System.out.println("1=" + ctmp);
	                     break;  
	                case 2:     //生成汉字  
	                     String[] rBase={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};   
	                     //生成第一位区码  
	                     int r1=random.nextInt(3)+11;  
	                     String str_r1=rBase[r1];  
	                     //生成第二位区码  
	                     int r2;  
	                     if(r1==13){  
	                         r2=random.nextInt(7);     
	                     }else{  
	                         r2=random.nextInt(16);  
	                     }  
	                     String str_r2=rBase[r2];  
	                     //生成第一位位码  
	                     int r3=random.nextInt(6)+10;  
	                     String str_r3=rBase[r3];  
	                     //生成第二位位码  
	                     int r4;  
	                     if(r3==10){  
	                         r4=random.nextInt(15)+1;  
	                     }else if(r3==15){  
	                         r4=random.nextInt(15);  
	                     }else{  
	                         r4=random.nextInt(16);  
	                     }  
	                     String str_r4=rBase[r4];  
	                     //将生成的机内码转换为汉字  
	                     byte[] bytes=new byte[2];  
	                     //将生成的区码保存到字节数组的第一个元素中  
	                     String str_12=str_r1+str_r2;  
	                     int tempLow=Integer.parseInt(str_12, 16);  
	                     bytes[0]=(byte) tempLow;  
	                     //将生成的位码保存到字节数组的第二个元素中  
	                     String str_34=str_r3+str_r4;  
	                     int tempHigh=Integer.parseInt(str_34, 16);  
	                     bytes[1]=(byte)tempHigh;  
	                     ctmp=new String(bytes,"gb2312");
	                     System.out.println("2=" + ctmp);
	                     break;  
	                default:  
	                     itmp=random.nextInt(10)+48;  
	                     ctmp=String.valueOf((char)itmp);
	                     System.out.println("default=" + ctmp);
	                     break;  
	            }  
	            sRand+=ctmp;
	            System.out.println("sRand=" + sRand);
	            Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));  
	            g.setColor(color);  
	            //将生成的随机数进行随机缩放并旋转制定角度 PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示  
	            /*将文字旋转制定角度*/  
	            Graphics2D g2d_word=(Graphics2D)g;  
	            AffineTransform trans=new AffineTransform();  
	            trans.rotate((45)*3.14/180,15*i+8,7);  
	            /*缩放文字*/  
	            float scaleSize=random.nextFloat()+0.8f;  
	            if(scaleSize>1f) scaleSize=1f;  
	            trans.scale(scaleSize, scaleSize);  
	            g2d_word.setTransform(trans);  
	            g.drawString(ctmp, 15*i+18, 4);  
	        }
	        HttpSession session=request.getSession(true);  
	        session.setAttribute("randCheckCode", sRand);  
	        g.dispose();    //释放g所占用的系统资源  
	        ImageIO.write(image,"JPEG",response.getOutputStream()); //输出图片  
	    }  ;


	 
	
	/**
	 * 检测name是否已经存在
	 * 
	 * @param req
	 * @param resp
	 * @throws IOException
	 * @author xm
	 */
	public void checkUserName(HttpServletRequest req,HttpServletResponse resp) throws IOException{
		//得到用户输入的用户名
		String userName = req.getParameter("userName");
		//如果存在该用户名
		if(us.checkUserName(userName)) {
			//输出0
			resp.getWriter().println("0");
		} else {
			resp.getWriter().println("1");
		}
	}
	/**
	 * 注册
	 * 
	 * @param req
	 * @param resp
	 * @return
	 * @throws IOException
	 * @author xm
	 */
	public String register(HttpServletRequest req,HttpServletResponse resp) throws IOException{
		 String checkcode=req.getParameter("checkCode");
		  HttpSession session = req.getSession(true);
			if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){ 
				resp.getWriter().println("验证码不正确！！");
				return null;
			}
		//接收数据 放在map集合里
		Map<String, String[]> map = req.getParameterMap();
		//创建一个新的用户对象
		User register= new User();
		try {
			//封装用户对象
			BeanUtils.populate(register, map);
			//设置用户密码并加密
			register.setPassword(MD5.entryptPassword(register.getPassword()));
			register.setType("user");
			register.setAuditFlag(0);
			Date d = new Date();
			register.setCreateDate(d);
			register.setUpdateDate(d);
			register.setDeleteFlag(0);
			//调用service层保存用户对象，返回result
			int result = us.save(register);
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
	
		//跳转到登录页面
		return "index.jsp";
	}
	/**
	 * 检查用户是否过期
	 * 
	 * @param request
	 * @param response
	 * @return  Strng
	 * @throws IOException
	 * @author xm
	 */
	
	public String check(HttpServletRequest request,HttpServletResponse response) throws IOException{
		//得到用户信息
		User existUser = (User) request.getSession().getAttribute("existUser");
		//判断用户信息是否存在
		if(existUser == null){
			//如果用户不存在输出1
			response.getWriter().println("1");
		}else{
			response.getWriter().println("2");
		}
		
		return null;
		
	}
	/**
	 * 退出聊天室
	 * @throws IOException 
	 */
	public String exit(HttpServletRequest request,HttpServletResponse response) throws IOException{
		//获得session 对象
		HttpSession session = request.getSession();
		//销毁session
		session.invalidate();
		//重定向
		response.sendRedirect(request.getContextPath()+"/index.jsp");
		return null;
		
	}
	/**
	 * 发送聊天内容
	 * @return  String
	 * @throws IOException 
	 */
	public String sendMessage(HttpServletRequest req,HttpServletResponse resp) throws IOException{
	
		//1.接收数据
		System.out.println("sendMessage invoke....");
		String from = req.getParameter("from");//发言人
		String face = req.getParameter("face");//表情
		String to = req.getParameter("to");//接收者
		String color = req.getParameter("color");//字体颜色
		String content = req.getParameter("content");//发言内容
		//正常情况下使用SimpleDateFormat
		String sendTime = new Date().toLocaleString();//发言时间
		//获得ServletContext对象
		ServletContext application = getServletContext();
		//从ServletContext中获取消息
		String sourceMessage = (String) application.getAttribute("message");
		//拼接发言内容：
		sourceMessage += "<font color='blue'><strong>"+from
                +"</strong></font><font color='#cc0000'>"+face 
		        +"</font>对<font color='green'>["+to+"]</font>说:"
				+"<font color='"+color +"'>" +content +"</font>("
				+ sendTime + ") <br>";
		//将消息存放在application的范围
		application.setAttribute("message", sourceMessage);
				//转向页面getMessage
				return getMessage(req,resp);
		
	}
	/**
	 * 获取消息的方法
	 * @throws IOException 
	 */
	public String getMessage(HttpServletRequest req,HttpServletResponse resp) throws IOException{
	//从ServletContext()域中获取输入的消息
		String message = (String) getServletContext().getAttribute("message");
		//如果消息不为空
		if(message !=null){
			//服务器就输出消息的内容
			resp.getWriter().println(message);
		}
		return null;
		
	}
	/**
	 * 踢人的功能
	 * 
	 * @param req
	 * @param resp
	 * @return String
	 * @author xm
	 * @throws IOException 
	 */
	public String kick(HttpServletRequest req,HttpServletResponse resp) throws IOException{
		//1.接收参数
		int id = Integer.parseInt(req.getParameter("id"));
		//2.踢人：从userMap中将用户对应的session销毁.
		//获得userMap 集合(在线列表)
		Map<User,HttpSession> userMap = (Map<User, HttpSession>) getServletContext().getAttribute("userMap");
		//获得这个用户对应的session.如何知道是哪个用户呢？ Id已经传递过来了，去数据库中查询.
		//重写user的equals和hashCode方法，那么只要用户的id相同就认为是同一个用户.
		User user = new User();
		//向用户中传入id
		user.setId(id);
		//从Map集合中获得用户对应的session
		HttpSession session = userMap.get(user);
		//销毁session
		session.invalidate();
		//重定向到聊天页面
		resp.sendRedirect(req.getContextPath()+"/main.jsp");
		return null;
	}
	
	/**
	 * 登录的方法
	 * 
	 * @param req
	 * @param resp
	 * @return String
	 * @author xm
	 */
	public String login(HttpServletRequest req,HttpServletResponse resp){
		 String checkcode=req.getParameter("checkCode");
		  HttpSession session = req.getSession(true);
			try {
				if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){ 
					resp.getWriter().println("验证码不正确！！");
					return null;
				}
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		
		//接收数据 放在Map集合里
		Map<String, String[]> map = req.getParameterMap();
		//遍历集合数据
		for(String s : map.keySet()) {
			String[] arr = map.get(s);
			System.out.println(s + "-->" + arr[0]);
		}
		//创建一个新的user
		User user = new User();
		try {
			//封装数据
			BeanUtils.populate(user, map);
			//输出User里面的用户名和用户密码
			System.out.println(user.getUsername() + "                 " + user.getPassword());
			//得到user里面的用户密码并加密
			user.setPassword(MD5.entryptPassword(user.getPassword()));
			//调用UserService层处理数据。调用login的方法返回一个existUser
			User existUser = us.login(user);
			//如果用户为空
			if(existUser == null){
				//返回用户登录失败的信息
				req.setAttribute("msg", "用户名或密码错误！");
				//跳转到登录页面
				return "/index.jsp";
			} else{
				//用户登录成功
				//第一个BUG的解决：第二个用户登录之后将之前的session销毁
				req.getSession().invalidate();
				
				//第二个BUG的解决：判断用户是否已经在Map集合中，存在：已经在列表中。销毁其session.
				//获得到ServletContext中存在的Map集合.
				Map<User,HttpSession> userMap = (Map<User, HttpSession>) getServletContext().getAttribute("userMap");
				//判断用户是否已经在map集合中.
				if(userMap.containsKey(existUser)){
					//说明map中有这个用户.
					session = userMap.get(existUser);
					//将这个session销毁
					session.invalidate();
				}
				//使用监听器：HttpSessionBandListener;作用在javaBean上的监听器
				//用Session()将用户信息保存
				req.getSession().setAttribute("existUser", existUser);
				//得到ServletContext的域
				ServletContext application = getServletContext();
				//定义一个消息sourceMessage
				String sourceMessage = "";
				//从ServletContext域中获取消息，如果不为空
				if (null != application.getAttribute("message")) {
					//就取出来 给sourceMessage赋值
					sourceMessage = application.getAttribute("message")
							.toString();
				}
				//如果不为空，第一次登录就显示公告+用户名+走进了聊天室
				sourceMessage += "系统公告：<font color='gray'>"
						+ existUser.getUsername() + "走进了聊天室！</font><br>";
				//把这个消息再存到ServletContext域中
				application.setAttribute("message", sourceMessage);
				//重定向到聊天页面
				resp.sendRedirect(req.getContextPath() + "/main.jsp");
				//不转发
				return null;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 return null;
	}

}
